package com.apes.fico.finance.service;

import com.apes.fico.finance.respository.ChartAmoutRepository;
import com.apes.fico.finance.respository.ChartAuxRepository;
import com.apes.fico.finance.respository.InitAuxRepository;
import com.apes.fico.finance.respository.InitBalanceRepository;
import com.apes.framework.api.DomainService;
import com.apes.framework.plugin.esb.api.SimpleRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @ClassName GeneralLedgerService
 * @Description TODO
 * @Author pengyb
 * @Date 2019/3/14 11:30
 * @Version 1.0
 **/
@Service("generalLedgerService")
public class GeneralLedgerService extends DomainService {
    @Autowired
    private ChartAmoutRepository chartAmoutRepository;

    @Autowired
    private ChartAuxRepository chartAuxRepository;

    @Autowired
    private InitBalanceRepository initBalanceRepository;

    @Autowired
    private InitAuxRepository initAuxRepository;

    /**
     * 查询财务总分类账
     *
     * @param request
     * @return
     */
    public List<Map<String, Object>> findAll(SimpleRequest request) {
        List<Map<String, Object>> maps = new ArrayList<>();

        //取值
        String company = request.get("company");
        int year = request.get("year");
        int stopYear = request.get("stopYear");
        int stopPeriod = request.get("stopPeriod");
        int period = request.get("period");
        String accId = request.get("accId"); ///科目id
        String accCode = request.get("accCode"); ///科目id
        String classes = request.get("classes");    //科目级次
        String stopClasses = request.get("stopClasses");    //科目级次
        if (accId == null && classes == null || stopClasses == null) throw new RuntimeException("请选择级别或者科目！");


        List<Map<String, Object>> chartAmoutMaps;
        List<Map<String, Object>> chartAuxMaps;
        List<Map<String, Object>> initBalances; //初始化余额
        List<Map<String, Object>> initAuxs;
        if (classes != null && accCode == null) {
            //直接取余额表信息（选择科目级别时）
            chartAmoutMaps = chartAmoutRepository.findByBody(company, period, stopPeriod, year, stopYear, Double.parseDouble(classes), Double.parseDouble(stopClasses));
            chartAuxMaps = chartAuxRepository.findByBody(company, period, stopPeriod, year, stopYear, Double.parseDouble(classes), Double.parseDouble(stopClasses));

            initBalances = initBalanceRepository.findByCompanyAndYear(company, year, stopYear);
            initAuxs = initAuxRepository.findByCompanyAndYear(company, year, stopYear);

        } else {
            //直接取余额表信息（选择科目时）
            chartAmoutMaps = chartAmoutRepository.findByBodyAndAccCode(company, accCode, period, stopPeriod, year, stopYear);
            chartAuxMaps = chartAuxRepository.findByBodyAndAccCode(company, accCode, period, stopPeriod, year, stopYear);

            initBalances = initBalanceRepository.findAllByCompanyAndBetwennYearAndAccountCode(company, accCode, year, stopYear);
            initAuxs = initAuxRepository.findAllByCompanyAndBetwennYearAndAccountCode(company, accCode, year, stopYear);

        }
        /*--------------------------------------------------------------------------------------- */
        //合并2个年初余额集合到map中(会计年度+科目代码为key,值为value)
        Map<String, Map<String, Object>> initMap = new HashMap<>();
        if (!initBalances.isEmpty() && initBalances.size() != 0) {
            for (Map<String, Object> map : initBalances) {
                initMap.put(map.get("year") + "+" + map.get("code"), map);
            }
        }

        if (!initAuxs.isEmpty() && initAuxs.size() != 0) {
            for (Map<String, Object> map : initAuxs) {
                initMap.put(map.get("year") + "+" + map.get("code"), map);
            }
        }


        //合并2个集合到map中(会计年度+科目代码为key，值为value)==手动分组
        Map<String, List<Map<String, Object>>> chartMap = new HashMap<>(); //合并后的map

        if (!chartAmoutMaps.isEmpty() && chartAmoutMaps.size() != 0) {
            for (Map<String, Object> map : chartAmoutMaps) {
                if (chartMap.containsKey(map.get("year") + "+" + map.get("code"))) {
                    List<Map<String, Object>> mapList = chartMap.get(map.get("year") + "+" + map.get("code"));
                    mapList.add(map);
                    chartMap.put(map.get("year") + "+" + map.get("code"), mapList);

                } else {
                    List<Map<String, Object>> mapList = new ArrayList<>();
                    mapList.add(map);
                    chartMap.put(map.get("year") + "+" + map.get("code").toString(), mapList);
                }
            }
        }
        if (!chartAuxMaps.isEmpty() && chartAuxMaps.size() != 0) {
            for (Map<String, Object> map : chartAuxMaps) {
                if (chartMap.containsKey(map.get("year") + "+" + map.get("code"))) {
                    List<Map<String, Object>> mapList = chartMap.get(map.get("year") + "+" + map.get("code"));
                    mapList.add(map);
                    chartMap.put(map.get("year") + "+" + map.get("code"), mapList);

                } else {
                    List<Map<String, Object>> mapList = new ArrayList<>();
                    mapList.add(map);
                    chartMap.put(map.get("year") + "+" + map.get("code"), mapList);
                }
            }
        }

        /*--------------------------------------------------------------------------------------- */
        //直接遍历。已经根据年份和科目代码分组了
        for (Map.Entry<String, List<Map<String, Object>>> entry : chartMap.entrySet()) {
            double yearOpeningBalance = 0;
            if (!initMap.isEmpty() && initMap.containsKey(entry.getKey())) {
                yearOpeningBalance = (double) initMap.get(entry.getKey()).get("openingBalance"); //年初余额
            }

            double yearTotalCredit = 0;     //本年累计(贷方)
            double yearTotalDebit = 0;      //本年累计(借方)
            //因为hashMap的无序性先排序再运算
            List<Map<String, Object>> entryValue = entry.getValue().stream().sorted(Comparator.comparing(e -> Long.parseLong(e.get("period").toString()))).collect(Collectors.toList());
            for (int i = 0; i < entryValue.size(); i++) {

                double credit = (double) entryValue.get(i).get("credit"); //贷方
                double debit = (double) entryValue.get(i).get("debit"); //借方
                double openingBalance = (double) entryValue.get(i).get("openingBalance");     //期初余额
                double balance;             //余额
                //调整余额方向
                String balanorient = entryValue.get(i).get("balanorient").toString();  //余额方向
                balanorient = balanorient.equals("0") ? "借" : "贷";

                if (balanorient.equals("借")) {
                    if (openingBalance + (debit - credit) < 0) {  //保证余额为正数(余额借贷方向调整)
                        balanorient = balanorient.equals("借") ? "贷" : "借";
                    } else if (openingBalance + (debit - credit) == 0) {  //借贷持平 则为平
                        balanorient = "平";
                    }
                } else if (balanorient.equals("贷")) {
                    if (openingBalance + ((debit - credit) * -1.0) < 0) {  //保证余额为正数(余额借贷方向调整)
                        balanorient = balanorient.equals("借") ? "贷" : "借";
                    } else if (openingBalance + (debit - credit) == 0) {  //借贷持平 则为平
                        balanorient = "平";
                    }
                }


                //根据余额方向调整余额计算
                if (balanorient.equals("借")) {          //借方
                    balance = openingBalance + (debit - credit);            //借方-贷方
                } else if (balanorient.equals("贷")) {   //贷方
                    balance = openingBalance + ((debit - credit) * -1.0);          //贷方-借方
                } else {
                    balance = openingBalance + (debit - credit);         //借方-贷方
                }
                Map map = new HashMap();
                map.put("ACC_OPERATING_CHART_CODE", entryValue.get(i).get("code"));
                map.put("NAME", entryValue.get(i).get("name"));
                map.put("YEAR", entryValue.get(i).get("year"));
                map.put("PERIOD", entryValue.get(i).get("period"));
                map.put("CREDIT", credit);
                map.put("DEBIT", debit);
                map.put("BALANORIENT", balanorient);
                map.put("BALANCE", balance);
                map.put("SUMMARY", "本期合计");
                maps.add(map);
                yearTotalCredit += credit;
                yearTotalDebit += debit;
            }
            Map map = new HashMap();
            map.put("ACC_OPERATING_CHART_CODE", entryValue.get(0).get("code"));
            map.put("NAME", entryValue.get(0).get("name"));
            map.put("YEAR", entryValue.get(0).get("year"));
            map.put("PERIOD", entryValue.get(entryValue.size() - 1).get("period"));
            map.put("CREDIT", yearTotalCredit + (!initMap.isEmpty() && initMap.containsKey(entry.getKey()) ? ((double) initMap.get(entry.getKey()).get("credit")) : 0));
            map.put("DEBIT", yearTotalDebit + (!initMap.isEmpty() && initMap.containsKey(entry.getKey()) ? ((double) initMap.get(entry.getKey()).get("debit")) : 0));
            map.put("BALANORIENT", (double) map.get("CREDIT") == (double) map.get("DEBIT") ? "平" : ((double) map.get("CREDIT") > (double) map.get("DEBIT")) ? "贷" : "借");
            map.put("BALANCE", (double) map.get("CREDIT") < (double) map.get("DEBIT") ? (double) map.get("DEBIT") - (double) map.get("CREDIT") + yearOpeningBalance
                    : ((double) map.get("DEBIT") - (double) map.get("CREDIT") + yearOpeningBalance) * -1.0

            );

            map.put("SUMMARY", "本年累计");
            maps.add(map);
        }


        //因为hashMap的无序性排序后返回
//        return maps.stream().sorted(Comparator.comparing((Map<String, Object> e) -> e.get("NAME").toString())
//                .thenComparing((Map<String, Object> x) -> Long.parseLong(x.get("PERIOD").toString()))).collect(Collectors.toList());
        return maps;

    }

}
